#ifndef VIRTUALFILESYSTEM_H_
#define VIRTUALFILESYSTEM_H_

#include "includes/libFUSE.h"
#include "includes/libExtended2.h"

#define PATH_MAXSIZE 100
#define MODO_MAXSIZE 100
#define SIZE_MAXSIZE 100
#define OFFSET_MAXSIZE 100
#define BUF_MAXSIZE 30000

void inicializarConsola(void) {

	uint8_t ejecutar;
	uint8_t terminar = 0;

	while (terminar == 0) {
		printf("===============================================================================\n");
		printf("Menú de operaciones\n");
		printf("-------------------------------------------------------------------------------\n");
		printf("> 0: Crear un archivo                                             fs_create\n");
		printf("> 1: Abrir un archivo                                             fs_open\n");
		printf("> 2: Leer un archivo                                              fs_read\n");
		printf("> 3: Escribir un archivo                                          fs_write\n");
		printf("> 4: Liberar un archivo                                           fs_release\n");
		printf("> 5: Truncar un archivo                                           fs_ftruncate\n");
		printf("> 6: Borrar un archivo                                            fs_unlink\n");
		printf("> 7: Crear un directorio                                          fs_mkdir\n");
		printf("> 8: Leer un directorio                                           fs_readdir\n");
		printf("> 9: Borrar un directorio                                         fs_rmdir\n");
		printf("> A: Obtener los atributos de un elemento                         fs_getattr\n");
		printf("> X: Terminar \n");

		printf("===============================================================================\n");
		printf("Ingrese el caracter correspondiente a la operación que desea ejecutar: ");

		char operacion[2];

		scanf("%s", operacion);

		if (operacion[0] == '0') {
			printf("===============================================================================\n");
			printf("Crear un archivo                                                     fs_create\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del archivo a crear \n");
			printf("> modo: Modo de acceso \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {

				printf("path > ");
				char create_path[PATH_MAXSIZE];
				scanf("%s", create_path);

				printf("modo > ");
				char create_buf_modo[MODO_MAXSIZE];
				scanf("%s", create_buf_modo);

				uint32_t create_modo = atoi(create_buf_modo);

				struct fuse_file_info create_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_create() con los siguientes parámetros: \n");
				printf("> path: %s \n", create_path);
				printf("> modo: %i \n\n", create_modo);
				printf("¿Son estos datos correctos? (S/N) > ");

				char create_confirmacion[2];
				scanf("%s", create_confirmacion);

				if (create_confirmacion[0] == 'S' || create_confirmacion[0] == 's') {
					fs_create(create_path, (mode_t) create_modo, &create_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '1') {
			printf("===============================================================================\n");
			printf("Abrir un archivo                                                       fs_open\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del archivo a abrir \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {

				printf("path > ");
				char open_path[PATH_MAXSIZE];
				scanf("%s", open_path);

				struct fuse_file_info open_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_open() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", open_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char open_confirmacion[2];
				scanf("%s", open_confirmacion);

				if (open_confirmacion[0] == 'S' || open_confirmacion[0] == 's') {
					fs_open(open_path, &open_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '2') {
			printf("===============================================================================\n");
			printf("Leer un archivo                                                        fs_read\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path:   Ruta completa del archivo a leer \n");
			printf("> size:   Tamaño de los datos a leer \n");
			printf("> offset: Punto desde el cual comenzar la lectura \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {

				printf("path > ");
				char read_path[PATH_MAXSIZE];
				scanf("%s", read_path);

				printf("size > ");
				char read_buf_size[SIZE_MAXSIZE];
				scanf("%s", read_buf_size);

				uint32_t read_size = atoi(read_buf_size);

				printf("offset > ");
				char read_buf_offset[OFFSET_MAXSIZE];
				scanf("%s", read_buf_offset);

				uint32_t read_offset = atoi(read_buf_offset);

				struct fuse_file_info read_file_info;
				char *read_buffer = (char*) malloc(read_size);

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_read() con los siguientes parámetros: \n");
				printf("> path: %s \n", read_path);
				printf("> size: %i \n", read_size);
				printf("> offset: %i \n\n", read_offset);
				printf("¿Son estos datos correctos? (S/N) > ");

				char read_confirmacion[2];
				scanf("%s", read_confirmacion);

				if (read_confirmacion[0] == 'S' || read_confirmacion[0] == 's') {
					fs_read(read_path, read_buffer, (size_t) read_size, (off_t) read_offset, &read_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '3') {
			printf("===============================================================================\n");
			printf("Escribir un archivo                                                   fs_write\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path:   Ruta completa del archivo a escribir \n");
			printf("> offset: Punto desde el cual comenzar la escritura \n");
			printf("> buffer: Contenido a escribir \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {

				printf("path > ");
				char write_path[PATH_MAXSIZE];
				scanf("%s", write_path);

				printf("offset > ");
				char write_buf_offset[OFFSET_MAXSIZE];
				scanf("%s", write_buf_offset);

				uint32_t write_offset = atoi(write_buf_offset);

				printf("buffer > ");
				char write_buffer[BUF_MAXSIZE];
				scanf("%s", write_buffer);

				size_t write_size = strlen(write_buffer);
				struct fuse_file_info write_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_write() con los siguientes parámetros: \n");
				printf("> path: %s \n", write_path);
				printf("> offset: %i \n", write_offset);
				printf("> buffer: %s (Caracteres: %i) \n\n", write_buffer, (uint32_t) write_size);
				printf("¿Son estos datos correctos? (S/N) > ");

				char write_confirmacion[2];
				scanf("%s", write_confirmacion);

				if (write_confirmacion[0] == 'S' || write_confirmacion[0] == 's') {
					fs_write(write_path, write_buffer, write_size, write_offset, &write_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '4') {
			printf("===============================================================================\n");
			printf("Liberar un archivo                                                  fs_release\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del archivo a liberar \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char release_path[PATH_MAXSIZE];
				scanf("%s", release_path);

				struct fuse_file_info release_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_release() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", release_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char release_confirmacion[2];
				scanf("%s", release_confirmacion);

				if (release_confirmacion[0] == 'S' || release_confirmacion[0] == 's') {
					fs_release(release_path, &release_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '5') {
			printf("===============================================================================\n");
			printf("Truncar un archivo                                                fs_ftruncate\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path:   Ruta completa del archivo a truncar \n");
			printf("> offset: Cantidad de bytes a truncar del archivo \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char ftruncate_path[PATH_MAXSIZE];
				scanf("%s", ftruncate_path);

				printf("offset > ");
				char ftruncate_buf_offset[OFFSET_MAXSIZE];
				scanf("%s", ftruncate_buf_offset);

				uint32_t ftruncate_offset = atoi(ftruncate_buf_offset);
				struct fuse_file_info ftruncate_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_ftruncate() con los siguientes parámetros: \n");
				printf("> path: %s \n", ftruncate_path);
				printf("> offset: %i \n\n", ftruncate_offset);
				printf("¿Son estos datos correctos? (S/N) > ");

				char ftruncate_confirmacion[2];
				scanf("%s", ftruncate_confirmacion);

				if (ftruncate_confirmacion[0] == 'S' || ftruncate_confirmacion[0] == 's') {
					fs_ftruncate(ftruncate_path, (off_t) ftruncate_offset, &ftruncate_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '6') {
			printf("===============================================================================\n");
			printf("Borrar un archivo                                                    fs_unlink\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del archivo a borrar \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char unlink_path[PATH_MAXSIZE];
				scanf("%s", unlink_path);

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_unlink() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", unlink_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char unlink_confirmacion[2];
				scanf("%s", unlink_confirmacion);

				if (unlink_confirmacion[0] == 'S' || unlink_confirmacion[0] == 's') {
					fs_unlink(unlink_path);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '7') {
			printf("===============================================================================\n");
			printf("Crear un directorio                                                   fs_mkdir\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del directorio a crear \n");
			printf("> modo: Modo de acceso\n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char mkdir_path[PATH_MAXSIZE];
				scanf("%s", mkdir_path);

				printf("modo > ");
				char mkdir_buf_modo[MODO_MAXSIZE];
				scanf("%s", mkdir_buf_modo);

				uint32_t mkdir_modo = atoi(mkdir_buf_modo);

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_mkdir() con los siguientes parámetros: \n");
				printf("> path: %s \n", mkdir_path);
				printf("> modo: %i \n\n", mkdir_modo);
				printf("¿Son estos datos correctos? (S/N) > ");

				char mkdir_confirmacion[2];
				scanf("%s", mkdir_confirmacion);

				if (mkdir_confirmacion[0] == 'S' || mkdir_confirmacion[0] == 's') {
					fs_mkdir(mkdir_path, mkdir_modo);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '8') {
			printf("===============================================================================\n");
			printf("Leer un directorio                                                  fs_readdir\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del directorio a leer \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char readdir_path[PATH_MAXSIZE];
				scanf("%s", readdir_path);

				void *readdir_buf = NULL;
				fuse_fill_dir_t readdir_fill = NULL;
				off_t readdir_offset = 0;
				struct fuse_file_info readdir_file_info;

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_readdir() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", readdir_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char readdir_confirmacion[2];
				scanf("%s", readdir_confirmacion);

				if (readdir_confirmacion[0] == 'S' || readdir_confirmacion[0] == 's') {
					fs_readdir(readdir_path, readdir_buf, readdir_fill, readdir_offset, &readdir_file_info);
					ejecutar = 0;
				}
			}
		}

		if (operacion[0] == '9') {
			printf("===============================================================================\n");
			printf("Borrar un directorio                                                  fs_rmdir\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del directorio a borrar \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char rmdir_path[PATH_MAXSIZE];
				scanf("%s", rmdir_path);

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_rmdir() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", rmdir_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char rmdir_confirmacion[2];
				scanf("%s", rmdir_confirmacion);

				if (rmdir_confirmacion[0] == 'S' || rmdir_confirmacion[0] == 's') {
					fs_rmdir(rmdir_path);
					ejecutar = 0;
				}
			}
		}

		if ((operacion[0] == 'A') || (operacion[0] == 'a')) {
			printf("===============================================================================\n");
			printf("Obtener atributos de un elemento                                    fs_getattr\n");
			printf("-------------------------------------------------------------------------------\n");
			printf("Variables necesarias: \n");
			printf("> path: Ruta completa del elemento de interés \n");
			printf("-------------------------------------------------------------------------------\n");

			ejecutar = 1;

			while (ejecutar == 1) {
				printf("path > ");
				char getattr_path[PATH_MAXSIZE];
				scanf("%s", getattr_path);

				printf("-------------------------------------------------------------------------------\n");
				printf("Se ejecutará la función fs_getattr() con los siguientes parámetros: \n");
				printf("> path: %s \n\n", getattr_path);
				printf("¿Son estos datos correctos? (S/N) > ");

				char getattr_confirmacion[2];
				scanf("%s", getattr_confirmacion);

				struct stat stbuff;

				if (getattr_confirmacion[0] == 'S' || getattr_confirmacion[0] == 's') {
					fs_getattr(getattr_path, &stbuff);
					ejecutar = 0;
				}
			}
		}

		if ((operacion[0] == 'X') || (operacion[0] == 'x')) {
			printf("-------------------------------------------------------------------------------\n");
			printf("          ____                        ____                    __     \n");
			printf("         /\\  _`\\                     /\\  _`\\                 /\\ \\    \n");
			printf("         \\ \\ \\L\\ \\  __  __     __    \\ \\ \\L\\ \\  __  __     __\\ \\ \\   \n");
			printf("          \\ \\  _ <'/\\ \\/\\ \\  /'__`\\   \\ \\  _ <'/\\ \\/\\ \\  /'__`\\ \\ \\  \n");
			printf("           \\ \\ \\L\\ \\ \\ \\_\\ \\/\\  __/    \\ \\ \\L\\ \\ \\ \\_\\ \\/\\  __/\\ \\_\\ \n");
			printf("            \\ \\____/\\/`____ \\ \\____\\    \\ \\____/\\/`____ \\ \\____\\\\/\\_\\\n");
			printf("             \\/___/  `/___/> \\/____/     \\/___/  `/___/> \\/____/ \\/_/\n");
			printf("                        /\\___/                      /\\___/           \n");
			printf("                        \\/__/                       \\/__/            \n\n");
			printf("===============================================================================\n");
			terminar = 1;
		}
	}
	return;
}

#endif
